/*
 * Copyright (c) 2007 Compl Yue Still, All Rights Reserved.
 */

package hbi.wire.as3.host
{
	import flash.utils.*;
	import hbi.wire.ProtocolError;

	public class DataTagList implements IncomingTag
	{
		
		public function get tagValues():Array
		{
			return _values;
		}
		
		private var _values:Array = new Array();
		
		private var _length:int;
		
		public function DataTagList(length:int=-1)
		{
			this._length = length;
		}
		
		private var currentTag:DataTag = null;
		
		public function processIncomingData(input:IDataInput):Boolean
		{
			if(_length == 0) return true;
			
			tag_scan: while(input.bytesAvailable > 0)
			{
				if(currentTag == null)
				{
					var tag:uint = input.readUnsignedByte();
					switch(tag)
					{
					case 'z'.charCodeAt(): // end of list
						if(_length > 0)
						{
							// assert _values.length < _length : "or we should have finished";
							throw new ProtocolError("Incomplete data tag list.");
						}
						return true;
					case 'N'.charCodeAt(): // null
						_values.push(null);
						if(_length > 0 && _values.length >= _length)
							return true;
						continue tag_scan;
					case 'T'.charCodeAt(): // boolean true
						_values.push(true);
						if(_length > 0 && _values.length >= _length)
							return true;
						continue tag_scan;
					case 'F'.charCodeAt(): // boolean false
						_values.push(false);
						if(_length > 0 && _values.length >= _length)
							return true;
						continue tag_scan;
					case 'I'.charCodeAt(): // 32-bits integer
						currentTag = new Int32();
						break;
					case 'L'.charCodeAt(): // 64-bits integer
						currentTag = new Int64();
						break;
					case 'D'.charCodeAt(): // 64-bits floating point number
						currentTag = new FP64();
						break;
					case 'd'.charCodeAt(): // 64-bits UTC date
						currentTag = new UTCDate();
						break;
					case 's'.charCodeAt(): // non-final string chunk
						currentTag = new UTF8Chunks(false);
						break;
					case 'S'.charCodeAt(): // final string chunk
						currentTag = new UTF8Chunks(true);
						break;
					case 'b'.charCodeAt(): // non-final binary chunk
						currentTag = new BinaryChunks(false);
						break;
					case 'B'.charCodeAt(): // final binary chunk
						currentTag = new BinaryChunks(true);
						break;
					case '['.charCodeAt(): // typed array
						currentTag = new TypedArray();
						break;
					case ']'.charCodeAt(): // untyped array
						currentTag = new UntypedArray();
						break;
					default:
						throw new ProtocolError("Bad data tag: " + tag);
					}
				}
				if(currentTag.processIncomingData(input))
				{
					_values.push(currentTag.tagValue);
					currentTag = null;
					
					if(_length > 0 && _values.length >= _length)
						return true;
				}
				else
				{
					break tag_scan;
				}
			}
			return false;
		}
		
	}
}
